/*
* @Author: 窦子滨<zibin_5257@163.com>
* @Date: 2019-05-07 9:49
 */
package main

import (
	"errors"
	"math/rand"
	"sync"
)

//手动配置的服务 优先级高于服务发现

type urlList []string

//手动配置的微服务
var manualList manual = NewManual()

type manual interface {
	//ServiceBase
	//首次配置 必须通过该方法进行添加
	Add(name string, list urlList) (err error)
	Delete(name string)
	Get(name string) (urlList, error)
	All() map[string]urlList
	AddUrl(name string, uri string) (error)
	DeleteUrl(name string, uri string) (error)
	DoBalance(name string) (uri string, err error)
}

func NewManual() manual {
	return &manualMan{}
}

type manualMan struct {
	list       sync.Map
}

func (t *manualMan) Add(name string, list urlList) (err error) {
	if len(list) < 1 {
		return errors.New("url list error")
	}
	t.list.Store(name, list)
	return
}

func (t *manualMan) AddUrl(name string, uri string) (error) {
	var list urlList
	list, err := t.Get(name)
	if err != nil {
		return err
	}
	for _, v := range list {
		if v == uri {
			return errors.New("uri已存在")
		}
	}
	list = append(list, uri)
	_ = t.Add(name, list)
	return nil
}

func (t *manualMan) DeleteUrl(name string, uri string) error {
	var list urlList
	list, err := t.Get(name)
	if err != nil {
		return err
	}
	for k, v := range list {
		if v == uri {
			list = append(list[:k], list[k+1:]...)
			return nil
		}
	}
	return errors.New("uri不存在")
}

func (t *manualMan) Delete(name string) {
	t.list.Delete(name)
}

func (t *manualMan) Get(name string) (urlList, error) {
	if v, ok := t.list.Load(name); ok {
		return v.(urlList), nil
	}
	return nil, errors.New("not key")
}

func (t *manualMan) All() map[string]urlList {
	v := make(map[string]urlList, 0)
	t.list.Range(func(key, value interface{}) bool {
		v[key.(string)] = value.(urlList)
		return true
	})
	return v
}

func (t *manualMan) DoBalance(name string) (uri string, err error) {
	var v urlList

	v, err = t.Get(name)
	if err != nil {
		return "", err
	}

	lens := len(v)
	if lens == 0 {
		err = errors.New("No url")
		return
	}

	if lens == 1 {
		uri = v[0]
	} else {
		index := rand.Intn(lens)
		uri = v[index]
	}
	return uri,nil
	//service, err = t.GetService(name)
	//if err != nil {
	//	service = t.newService(name)
	//}
	//conn = service.NewAndGet(uri)
	//return conn, nil
}
